/**
 * @file tyw_msg.h
 * @author zhengchunyu (ait_zhengchunyu@163.com)
 * @brief  tyw_msg 是基于lifeng开发的消息处理模块，
 *         主要功能为基于循环队列原理实现了大数据量接收，
 *         解决了因为mcu性能原因导致硬件接口（spi,i2c,uart）在接收数据后 无法及时处理数据导致丢包
 *         
 * @version 0.1
 * @date 2023-11-28
 * 
 * @copyright Copyright (c) 2023
 * 
 */
#ifndef _TYW_MSG_H
#define _TYW_MSG_H

#include "../sn_config.h"


/**
 * @brief 协议格式
 * 
 * | HEAD1  | HEAD2 | data Length             | data Length chk  | Crc chk |  data   |
 * | 1byte  | 1byte |    2 bytes              |     2bytes       |  4bytes |  n bytes|
 * | 0xeb   |  0x90 |len=data + FRAME_HEAD_LEN|     ~len         | crc32   |   n     |
 * 
 */

#define FRAME_HEAD1   0xeb
#define FRAME_HEAD2   0x90

#define FRAME_HEAD_LEN              10            //帧头长度
#define FRAME_TX_BUFFER_LEN          0x40        //数据发送缓冲区长度
#define FRAME_RX_BUFFER_LEN          0x40       //数据接收缓冲区长度

enum FRAME_TYPE_t
{
    FRAME_SOC_TO_MCU =1,
    FRAME_MCU_TO_SOC,
    FRAME_MAX,
     
};

struct frame_head_t
{
    uint8_t head[2];
    uint8_t len[2];
    uint8_t lenChk[2];
    uint8_t crcChk[4];
};

typedef int(*user_data_func)(void *prvParam);
typedef void(*hal_send_msg_t)(uint8_t*,uint32_t);


struct frame_info_t
{
    struct frame_head_t head;
    uint32_t beginIdx;//起始位置
    uint32_t endIdx;//结束位置
    uint32_t rxCnt;
    uint32_t errCrcVal;//crc 错误计数
    uint32_t errRcvVal;//接收错误计数
    uint8_t *pTxBuf;
    uint8_t *pRxBuf;
    uint8_t *pRxData;//数据内容首地址
    uint8_t  dataLen;//数据长度
    //需要用户注册次函数接口
    void(*hal_send_msg)(uint8_t* pbuf,uint32_t len);
    /**
     * @brief 获取接收缓冲区
     * 
     * @return 返回当前缓冲区指针
     * 
     */
    uint8_t *(*get_recv_buffer     )(struct frame_info_t *dev);
    uint32_t (*get_error_crc       )(struct frame_info_t *dev);
    uint32_t (*get_error_rcv       )(struct frame_info_t *dev);
    void     (*add_msg_data        )(struct frame_info_t *dev,uint8_t data);
    void    (*send_msg             )(struct frame_info_t *dev,uint8_t *pUserData,uint16_t len);
    void (*frame_proc_looper   )(struct frame_info_t *dev,user_data_func  user_func);
    
};
/**
 * @brief tyw msg 模块 初始化
 * 
 * @param dev    获取 tyw msg 模块的  Instance 指针
 * @param data_proc_func 数据处理回调函数，用户同通过此函数，处理数据内容
 */
void tyw_msg_init(struct frame_info_t **dev,hal_send_msg_t func);

/**
 * Example usage:
 *  <pre>
 *  1. 在程序初始化阶段调用  void tyw_msg_init(struct frame_info_t **dev)
 *  2. 在接收数据位置 添加  add_msg_data(struct frame_info_t *dev,uint8_t data) 用于将数据加入到消息队列中
 *     下面例子 以uart 作为接收和发送数据的操作对象，中断接收，顺序发送。
 *      将接收数据函数 添加到放到uart 中断函数中
 * ***uart.c
 * extern struct frame_info_t *Instance;
 * void uart_interrupt()
 * {
 *    volatile uint8_t rx_data;
 *    ...
 *    rx_data = SCI1->RXD2;
 *    Instance->add_msg_data(Instance,rx_data);
 *    ...
 * }
 * 
 * ***main.c
 * 
 *  #define MY_DATA_LEN  1024   //此长度应大于最大数据长度
 *  struct frame_info_t *Instance;
 *  uint8_t rxData[MY_DATA_LEN];
 *  uint32_t dataLen = 0;
 * 
 *   
 * int main()
 * {
 *    uint8_t txbuf[8]={0x00,0x01,0x02,0x03,0x4,0x5,0x06,0x07}
 *    ... 
 *    tyw_msg_init(&Instance,UartSendData);
 *    ...
 * 
 *    while(1)
 *    {
 *         ...
 *        
 *         dataLen =  Instance->frame_proc_looper(Instance,rxData);
 *         if(dataLen > 0)//如果返回值大于0 说明数据成功接收
 *         {
 *           在此条件中进行数据处理   
 *         }
 * 
 *          //发送数据
 *          Instance->send_msg(dev,txbuf,8);
 *         ...
 *    }
 *   
 * }
 * 
 * 
 * 
 * </pre>
 * 
 */


#endif //

